#include "lcd_service.h"

int *mem_p = NULL; // lcd 内存映射全局变量
int lcd_fd;        // lcd文件标识符
extern _state state;  // 视频状态

// 缩小范围
void narrow_down(int *x, int *y) {
    float src_X = 1024, src_Y = 600;
    float dest_X = 800, dest_Y = 480;

    *x = (*x * 1.0) * (dest_X / src_X);
    *x = (int)(*x + 0.5); // 四舍五入
    if (*x >= MAX_WIDTH) {
        *x = MAX_WIDTH - 1;
    }

    *y = (*y * 1.0) * (dest_Y / src_Y);
    *y = (int)(*y + 0.5); // 四舍五入
    if (*y >= MAX_HEIGHT) {
        *y = MAX_HEIGHT - 1;
    }
}

// 触摸屏操作,获取点击的位置
int *get_touch_location(int *coord) {
    int count = 0;
    struct input_event ts_event; // 输入事件结构体
    int fd = open(TS_PATH, O_RDONLY);
    if (-1 == fd) {
        printf("open %s fail\n", TS_PATH);
        return NULL;
    }
    while (count < 2) {
        memset(&ts_event, 0, sizeof(struct input_event));
        read(fd, &ts_event, sizeof(struct input_event));
        if (ts_event.type == EV_ABS) {
            //判断是否为触摸屏事件
            if (ts_event.code == ABS_X) {
                // x轴
                coord[0] = ts_event.value;
                count++;
            }
            if (ts_event.code == ABS_Y) {
                // y轴
                coord[1] = ts_event.value;
                count++;
            }
        }
    }
    if (-1 != fd) {
        close(fd);
    }
    return coord;
}

// 获取图片信息
struct bitmap_info *get_picture_msg(const char *bpm_path, struct bitmap_info *info) {
    //打开图片
    int bmp_fd = open(bpm_path, O_RDONLY);
    if (bmp_fd == -1) {
        printf("bmp open error\n");
        return NULL;
    }
    // 读取文件头
    struct bitmap_header header;
    read(bmp_fd, &header, sizeof(header));
    if (header.type != BMP_TYPE) {
        // 判断文件类型
        printf("dest file type is not bmp\n");
        return NULL;
    }
    read(bmp_fd, info, sizeof(struct bitmap_info));
    close(bmp_fd);
    return info;
}

// 在任意位置显示图片
int show_bmp_anyplace(const char *bpm_path, int width, int height, int start_y, int start_x) {
    // 1.打开图片
    int bmp_fd = open(bpm_path, O_RDONLY);
    printf("bpm_path = %s\n", bpm_path);
    if (bmp_fd == -1) {
        printf("bmp open error\n");
        return -1;
    }
    // 2.图片文件光标偏移
    lseek(bmp_fd, 54, SEEK_SET);

    // 3.读取图片数据
    char bmp_buf[width * height * 3];
    int tmp_buf[width * height];
    read(bmp_fd, bmp_buf, sizeof(bmp_buf));
    // inversion_picture(bmp_buf, width, height, 3); // 图片像素旋转180°
    // 4.把3字节变成4字节
    for (int i = 0; i < width * height; i++) {
        tmp_buf[i] = 0x00 << 24 | bmp_buf[3 * i + 2] << 16 | bmp_buf[3 * i + 1] << 8 | bmp_buf[3 * i + 0];
    }
    // 5.将数据映射到LCD显示屏
    for (int y = start_y; y < (start_y + height); y++) {
        for (int x = start_x; x < (start_x + width); x++) {
            // 倒置输入
            mem_p[y * 800 + x] = tmp_buf[(height + start_y - 1 - y) * width + x - start_x];
        }
    }
    // for (int y = 0; y < height; y++) {
    //     for (int x = 0; x < width; x++) {
    //         mem_p[(y + start_y) * 800 + x + start_x] = tmp_buf[(height - 1 - y) * width + x];
    //     }
    // }
    printf("y=%d,x=%d\n", start_y, start_x);
    close(bmp_fd);
    return 0;
}

// 初始化lcd内存映射数组
int lcd_init() {
    lcd_fd = open(LCD_PATH, O_RDWR);
    if (lcd_fd == -1) {
        printf("open lcd error\n");
        return -1;
    }
    //屏幕内存映射
    mem_p = (int *)mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);
    // 白色背景
    for (int i = 0; i < 800 * 480; i++) {
        mem_p[i] = 0XFFFFFF;
    }
    // mem_p 就相当于是一块800*480大小的内存的首地址 --- LCD显示 屏
    if (mem_p == MAP_FAILED) {
        printf("mmap lcd error\n");
        return -1;
    }
    return 0;
}

// 将指定范围改为指定颜色
int lcd_fill(int cloror, int width, int height, int start_x, int start_y) {
    for (int y = start_y; y < (start_y + height); y++) {
        for (int x = start_x; x < (start_x + width); x++) {
            // 倒置输入
            mem_p[y * 800 + x] = cloror;
        }
    }
    return 0;
}

//解除映射
int lcd_uninit(void) {
    munmap(mem_p, 800 * 480 * 4);
    mem_p = NULL;
    //关闭文件
    close(lcd_fd);
}

// 显示底部按钮
int show_bottom_button() {
    // 左按钮显示
    struct bitmap_info prev_info;
    int prev_start_x = 40;  // 上一部按钮起始点x轴
    int prev_start_y = 400; // 上一部按钮起始点y轴
    if (NULL != get_picture_msg(PREV_PATH, &prev_info)) {
        // 按钮的尺寸是80*80
        show_bmp_anyplace(PREV_PATH, prev_info.width, prev_info.height, prev_start_y, prev_start_x);
    }

    // 左快进按钮显示
    struct bitmap_info left_info;
    int left_start_x = 160; // 左快进按钮起始点x轴
    int left_start_y = 400; // 左快进按钮起始点y轴
    if (NULL != get_picture_msg(LEFT_PATH, &left_info)) {
        // 按钮的尺寸是80*80
        show_bmp_anyplace(LEFT_PATH, left_info.width, left_info.height, left_start_y, left_start_x);
    }

    // 暂停按钮显示
    struct bitmap_info pause_info;
    int pause_start_x = 280; // 暂停按钮起始点x轴
    int pause_start_y = 400; // 暂停按钮起始点y轴
    if (NULL != get_picture_msg(PAUSE_PATH, &pause_info)) {
        // 按钮的尺寸是80*80
        show_bmp_anyplace(PAUSE_PATH, pause_info.width, pause_info.height, pause_start_y, pause_start_x);
    }

    // 左快进按钮显示
    struct bitmap_info right_info;
    int right_start_x = 400; // 右快进按钮起始点x轴
    int right_start_y = 400; // 右快进按钮起始点y轴
    if (NULL != get_picture_msg(RIGHT_PATH, &right_info)) {
        // 按钮的尺寸是80*80
        show_bmp_anyplace(RIGHT_PATH, right_info.width, right_info.height, right_start_y, right_start_x);
    }

    // 右按钮显示
    struct bitmap_info next_info;
    int next_start_x = 520; // 下一部按钮起始点x轴
    int next_start_y = 400; // 下一部按钮起始点y轴
    if (NULL != get_picture_msg(NEXT_PATH, &next_info)) {
        // 按钮的尺寸是80*80
        show_bmp_anyplace(NEXT_PATH, next_info.width, next_info.height, next_start_y, next_start_x);
    }

    return 0;
}

// 根据页面数显示右侧视频列表
int show_right_list(int page) {
    // 将列表改为空白
    lcd_fill(WHITE, 80, 350, 680, 65);
    int offset = (page - 1) * PAGE_NUM; // 偏移量
    int end_num = 0; // 最终的显示的位置
    if (page == state.count_page) { // 是最后一页
        end_num = state.count_video;
    } else {
        end_num = offset + PAGE_NUM;
    }
    state.page_video_num = end_num - offset;  // 获取当前一页的预览图数
    for (int i = offset, j = 0; i < end_num ; i++, j++) {
        struct bitmap_info preview_info;
        int preview_start_x = 680;            // 预览图起始点x轴
        int preview_start_y = 65 + (j * 90);  // 预览图起始点y轴
        char preview_path[128];               // 预览图地址
        memset(preview_path, 0, sizeof(preview_path));
        strcpy(preview_path, ((video *)(list->data[i]))->preview_path);
        printf("preview_path = %s\n", preview_path);
        if (NULL != get_picture_msg(preview_path, &preview_info)) {
            // 缩略图的尺寸是80*80
            show_bmp_anyplace(preview_path, preview_info.width, preview_info.height, preview_start_y, preview_start_x);
        }
    }
    return 0;
}

// 显示上下翻页键
int show_page_button() {
    // 上翻页按钮显示
    struct bitmap_info upward_info;
    int upward_start_x = 680; // 上翻页按钮起始点x轴
    int upward_start_y = 7;   // 上翻页按钮起始点y轴
    if (NULL != get_picture_msg(UPWARD_PATH, &upward_info)) {
        // 按钮的尺寸是80*48
        show_bmp_anyplace(UPWARD_PATH, upward_info.width, upward_info.height, upward_start_y, upward_start_x);
    }

    // 下翻页按钮显示
    struct bitmap_info down_info;
    int down_start_x = 680;   // 下翻页按钮起始点x轴
    int down_start_y = 425;   // 下翻页按钮起始点y轴
    if (NULL != get_picture_msg(DOWN_PATH, &down_info)) {
        // 按钮的尺寸是80*48
        show_bmp_anyplace(DOWN_PATH, down_info.width, down_info.height, down_start_y, down_start_x);
    }
    return 0;
}

// 显示进度框
int show_progress_dialog() {
    lcd_fill(BLACK, 610, 20, 15, 370);
    lcd_fill(WHITE, 600, 10, 20, 375);
}

// 根据进度百分比操作进度条
int show_progress_bar(int progress) {
    lcd_fill(WHITE, 600, 10, 20, 375);
    lcd_fill(BLACK, 6 * progress, 10, 20, 375);
}